//
//  ViewController.swift
//  learn
//
//  Created by temp on 2018/6/30.
//  Copyright © 2018年 lanlyc. All rights reserved.
//

import UIKit

class ViewControllerThree: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        struct Point{
            var x, y:Double
        }
        struct Size{
            var width, height:Double
        }
        struct Rect{
            var  origin: Point
            var  size : Size
        }
        let point1 = Point(x: 20, y: 30)//point1 并没有创建一个point对象  这个变量本身就含着这个结构体Point
        //的x,y，结构体本身就在这个变量里面，而不是指向谁在另外一个变量里面
        //point1常量里面的x,y是不能被修改的 因为x,y在结构体里面，因为你在试图修改这个常量的一部分，
        var point2 = Point(x: 22, y: 33)
        point2.x = 23 //point2里面的常量是可以被修改的
        
        let size = Size(width: 100, height: 100)
        let rect = Rect(origin: point1, size: size)
        //类与结构体有很多相似之处，都差不多，只是类可以继承，结构体不可以继承
        //值传递与引用值传递的区别，结构体的值在传输的时候它传输的是内部的值，它会拷贝结构体内部的所有的数据进行传递，相当于是一个传值的感觉
        //对象在传的过程中是传的对象的引用并不是对象的本身
        //有的时候是需要的结构体，有的时候是需要的对象引用
        //比如 var newFrame = window.frame 这个就是结构体传值，newFrame结构体的拷贝版本  newFrame.origin.x = 20.0
        //引用类型与实用类型的区别
        
        //引用类型的常量与变量
        //值类型的常量与变量(constants and variables  value types)
        
        //修改一个结构体 mutating a structure
        struct movePoint{
            var x, y:Double
            //如果你在结构体方法中修改结构体的某个变量值你就必须添加一个关键字mutating
            //mutating 这个关键字
           mutating func moveToTheRightBy(dx: Double) -> () {
                x += dx
            }
        }
        
        var moveP = movePoint(x: 44, y: 55)
        moveP.moveToTheRightBy(dx: 66)
        print("\(moveP.x)")
        //枚举 enumerations
        //swift中的枚举特别简单 花括号中写枚举的可能值
        //每个值都需要写一个case  然后再写你这个枚举值的名字 然后再写等号 等号的右边是1 就是这个枚举值的存储值
        enum Day: Int{
            case Monday = 1
            case Tuesday = 2
            case Wednesday = 3
            case Thursday = 4
            case Friday = 5
            case Saturday = 6
            case Sunday = 7
            //上面写的比较啰嗦可以用下面的写
            //case Monday = 1, Tuesday, Wednesday, Friday, Saturday, Sunday
        }
        
        let day = Day.Thursday //推导为枚举Day 类型
        //day 是Thursday  它会自动把左边的day 推导为Day类型 day 并不是里面的值，而就是Thursday本身
        //但是有些特殊情况下我们需要知道day后面存储的值是多少，或者说行值是多少在swift中可以采用toRaw()这个方法去返回行值
        //let dayNumber = Day.Thursday.toRow //推导为其内部存储Int类型
        //dayNumber 是4
        enum IllegalCharacter: Character{
            case Tab = "\t"
            case Return = "\n"
            case Underline = "_"
            case Dot = "."
            case WhiteSpace = " "
        }
        
        //如果说这个枚举本身就已经解释了这个枚举的含义，比如说我们的方向Direction
        //首先你没有必要去写Direction是基于整形去存储的，你也没有必要给这四个方向给个值，给个值也没有意义，你也不可能说我把Direction加一个字符串它是基于字符串的，把north等于north south等于south East等于East West等于West那也没有任何的意思
        //有些情况下我们枚举本身就解释枚举本身的意义，所以在这种情况下我们的枚举没有必要写它是基于什么类型的所以在这里我们的direction可以不跟任何类型
        enum Direction{
            case North, South, East, West
        }
        var direction = Direction.West //direction被推导为Direction类型
        direction = Direction.East
        direction = .North//因为它已经被推倒为Direction类型了，那么你在赋值的时候，因为Swift有很强的类型检查，所以你在赋值的时候只能赋值Direction类型的值
        //在swift优化下的UIKit框架下
        let label = UILabel()
        label.textAlignment = .right
        
        //枚举关联值的概念
        enum TrainStatus {
            case OnTime
            case Delayed(Int)
            //枚举的默认值
            init(){
                self = .OnTime
            }
            //我们还可以给枚举增加算值属性，不可以增加储值属性
            var description:String {
                switch self {
                case .OnTime:
                    return "准时到达"
                case .Delayed(let minutes):
                    return "延误 \(minutes)分钟"
                }
            }
        }
        
//        var status = TrainStatus.OnTime
//        status = .Delayed(42)//传到status里面不光是Delayed这个枚举的值，还有它关联的42这个值一起存到了 status这个变量中
        //枚举的功能特别强大，它跟结构体一样特别的变态，我们还可以为枚举定义一个初始化方法
//        print("列车\(status.description)")
//
//        func task(ii: Int){
//            print("列车kaole\(ii)")
//        }
//
//        8.repetitions(task: task)
//
//        var intStack = Stack<Int>()
//        intStack.push(element: 50)
//        intStack.pop()
//        var stringStack = Stack<String>()
//        stringStack.push(element: "hello")
//        stringStack.pop()

//        var ttjj: TiJi = TiJi(width: 10, height: 20, lenght: 30)
//        ttjj.increaseByFactor(factor: 10)
//        print("width\(ttjj.width)height\(ttjj.height)")
        
    }
    
//    let exerciseC = YYExerciseControllerTwo()
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
}

//类型嵌套，枚举，结构体，类可以嵌套过来嵌套过去
//class Train {
//    enum TrainStatus{
//        case OnTime
//        case Delayed(Int)
//        //枚举的默认值
//        init(){
//            self = .OnTime
//        }
//        //我们还可以给枚举增加算值属性，不可以增加储值属性
//        var description:String{
//            switch self {
//            case .OnTime:
//                return "准时到达"
//            case .Delayed(let minutes):
//                return "延误 \(minutes)分钟"
//            }
//        }
//    }
//    let status = TrainStatus()
//}

//Extensions是将现有代码增加额外能力,还可以加载在结构体上
//给结构体TiJi增加一个方法
//struct TiJi {
//    var width, height, lenght:Double
//}

//extension TiJi{
//    mutating func increaseByFactor(factor: Double){
//        width *= factor
//        height *= factor
//    }
//}

//extension Int{
//    func repetitions(task:(Int)->()) -> () {
//        for i in 0..<self{
//            task(i)
//        }
//    }
//}

//一个非泛型化的栈结构的结构体,现在是个整型的如果是string类型的那要声明一个StringStack类型的了
//struct IntStack {
//    var elements = [Int]()
//    mutating func push(element: Int){
//        elements.append(element)
//    }
//    mutating func pop()-> Int{
//       return elements.removeLast()
//    }
//}

//在swift中有一个泛型的
//struct Stack<T> {
//    var elements = [T]()
//    mutating func push(element: T){
//        elements.append(element)
//    }
//    mutating func pop()-> T{
//        return elements.removeLast()
//    }
//}


